# !/usr/bin/env python
# encoding: utf-8


"""
  @author: gaogao
  @file: iv_sweep.py
  @time: 2022/3/9 13:35
  @desc:固定波长下iv_sweep
"""
import time
from ATS.hardwarescan import conf_file_manager
from ATS.application.LCR_App.U2722A_App import U2722A_App
from ATS.application.LASER_App.L8164B_App import L8164B_App
from ATS.application.LASER_App.N7786C_App import N7786C_App
from matplotlib import pyplot as plt
from ATS.datamanager import data_transfer_station as DataTransferStation
from collections import namedtuple
from utils.log_util import loggings
from gui.driver.var_manager import VarManager


def iv_sweep_test(para):
    try:
        result_data = namedtuple("result_data", "subdie,test_item,curve_type,y_invert,test_result")
        l8164b_app = L8164B_App(para.l8164_setting["title"])
        l8164b_app.set_power_unit()
        l8164b_app.set_power_value(para.l8164_setting["power_value"])
        l8164b_app.set_wave_length(para.l8164_setting["wave_length"][0])
        l8164b_app.output_on()

        smu_setting = para.smu_setting
        smu_dict = {}
        # smu voltage_list channel nplc current_range current_limit //mode sweep
        #
        mes_plans_dict = {"var_func": None, "var1": None, "measure_func": None}
        init_set_list = []
        if smu_setting:
            for smu in smu_setting:
                if smu["smu"] not in smu_dict:
                    smu_dict[smu["smu"]] = U2722A_App(smu["smu"])
                current_inst = smu_dict[smu["smu"]]
                current_voltage_list = smu["voltage_list"]
                current_channel = smu["channel"]
                current_channel_nplc = smu["nplc"]
                current_channel_range = smu["current_range"]
                current_channel_limit = smu["current_limit"]
                init_set_list += [lambda y=current_channel,
                                         inst_obj=current_inst: inst_obj.output_state(0, y),
                                  lambda x=current_channel, inst_obj=current_inst: inst_obj.set_voltage_range(x),
                                  lambda x=current_channel_nplc, y=current_channel,
                                         inst_obj=current_inst: inst_obj.set_current_nplc(x, y),
                                  lambda x=current_channel_range, y=current_channel_limit,
                                         z=current_channel, inst_obj=current_inst: inst_obj.set_current_range_limit(x,
                                                                                                                    y,
                                                                                                                    z)]
                if smu["mode"] == "sweep":
                    mes_plans_dict["var1"] = current_voltage_list
                    mes_plans_dict["var_func"] = lambda volt, x=current_channel, inst_obj=current_inst: \
                        inst_obj.set_voltage(volt, x)
                else:
                    init_set_list += [lambda x=current_voltage_list[0], y=current_channel,
                                             inst_obj=current_inst: inst_obj.set_voltage(x, y)]

                if smu["is_measure"]:
                    mes_plans_dict["measure_func"] = lambda x=current_channel, inst_obj=current_inst: abs(
                        float(inst_obj.get_current_value(x)))

                init_set_list += [lambda y=current_channel,
                                         inst_obj=current_inst: inst_obj.output_state(1, y)]

            # set init
            for inst_set_func in init_set_list:
                inst_set_func()  # 设置SMU

            # read mes
            current_list = []  # result list
            mes_func = mes_plans_dict["measure_func"]
            if mes_func:  # mes func不为空
                if mes_plans_dict["var1"]:  # sweep
                    for volt in mes_plans_dict["var1"]:
                        mes_plans_dict["var_func"](volt)
                        current_list.append(mes_func())
                else:
                    current_list.append(mes_func())  # spot
            y_data = current_inst
            x_data = [float(i) for i in mes_plans_dict["var1"]]
            title_section = f"{VarManager().diex}-{VarManager().diey}-{VarManager().subdie_name}"
            if all([x_data, y_data]):
                y_data = [abs(i) for i in y_data]
                result_data(para.subdie, para.test_item, (x_data, y_data))
                DataTransferStation.get_DTS().postarraydata('test',
                                                            result_data(title_section, para.test_item, "line", False,
                                                                        (x_data, y_data)))
    except Exception as e:
        loggings.error("iv_sweep" + str(e))
    finally:
        close_all_channel()


def close_all_channel():
    U2722A_App("SMU2").close_all_channel()
    U2722A_App("SMU3").close_all_channel()
    U2722A_App("SMU4").close_all_channel()
    # B2901BLApp("SMU10").output_close()


def plot_curve(x_data, y_data):
    print(x_data, y_data)
    plt.yscale('log')
    plt.gca().invert_xaxis()
    plt.plot(x_data, y_data, "b")
    plt.xlabel("Voltage")
    plt.ylabel("Value")
    plt.grid(True)
    plt.show()


iv_sweep_test(locals()['para'])
